package org.example.ims.Service.Order.Impl;

import org.example.ims.DTO.StockInOutDTO;
import org.example.ims.Entity.Base.Warehouse;
import org.example.ims.Entity.Order.InStockDetail;
import org.example.ims.Entity.Order.InStockOrder;
import org.example.ims.Entity.Base.Product;
import org.example.ims.Repository.Order.InStockDetailRepository;
import org.example.ims.Repository.Order.InStockOrderRepository;
import org.example.ims.Repository.Base.ProductRepository;
import org.example.ims.Service.Order.InStockDetailService;
import org.example.ims.Utils.Detail;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@Service("inStockDetailService")
public class InStockDetailServiceImpl implements InStockDetailService {
    @Autowired
    private  InStockDetailRepository detailRepository;
    @Autowired
    private  InStockOrderRepository orderRepository;
    @Autowired
    private  ProductRepository productRepository;

    @Override
    public InStockDetail createDetail(InStockDetail detail) {
        validateRelatedEntities(detail);
        detail.setDetailId(10);

        return detailRepository.save(detail);
    }

    @Override
    public InStockDetail updateDetail(Integer detailId, InStockDetail detail) {
        InStockDetail existingDetail = detailRepository.findById(detailId)
                .orElseThrow(() -> new NoSuchElementException("InStockDetail not found with id: " + detailId));
        return detailRepository.save(existingDetail);
    }

    @Override
    public void deleteDetail(Integer detailId) {
        if (!detailRepository.existsById(detailId)) {
            throw new NoSuchElementException("InStockDetail does not exist with id: " + detailId);
        }
        detailRepository.deleteById(detailId);
    }

    @Override
    public InStockDetail getDetailById(Integer detailId) {
        return detailRepository.findById(detailId)
                .orElseThrow(() -> new NoSuchElementException("InStockDetail not found with id: " + detailId));
    }

    @Override
    public Page<InStockDetail> getAllDetails(Integer page, Integer size) {
        return detailRepository.findAll(PageRequest.of(page, size));
    }

    @Override
    public Page<InStockDetail> searchDetails(Integer orderId, Integer productId , Integer page, Integer size) {
        return detailRepository.findAll(buildSpecification(orderId, productId), PageRequest.of(page, size));
    }


    @Override
    public StockInOutDTO<Product> validityAssessment(List<InStockDetail> details, Warehouse warehouse) {
        //查询对应的商品id都存在+计算总容量，和对应仓库的可用容量进行比较

        //先查询productId对应的商品是否存在，异常就返回了。find（）.orElse
        //如果存在然后得到商品单位，不同单位的占据空间然后累加计算容量

        //遍历结果得到总容量，然后进行判断是否可行，不行就抛出异常
        //成功则将这里得到的Product返回

        int totalVolume = 0;
        List<Detail< Product>> info = new ArrayList<>();

        // 遍历入库详情，验证商品并计算总容量
        for (InStockDetail detail : details) {
            // 查询商品是否存在
            Product product =productRepository.findById(detail.getProductId())
                    .orElseThrow(() -> new IllegalArgumentException("商品不存在，ID: " + detail.getProductId()));

            // 计算商品体积（数量 * 单位体积）
            int productVolume = detail.getQuantity() ;
            //double productVolume = detail.getQuantity() *product.getUnitVolume();
            totalVolume += productVolume;

            Detail<Product> key =new Detail<>(product,detail.getQuantity());
            info.add(key);
        }
        // 验证仓库容量
        if (totalVolume > warehouse.getAvailableCapacity()) {
            throw new IllegalArgumentException("仓库容量不足，需要: " + totalVolume + "，可用: " + warehouse.getAvailableCapacity());
        }

        return new StockInOutDTO<>(info,totalVolume);
    }


    //findAll支持的一种查询形式，查询表达式中null直接省略，root对应InStockDetail
    private Specification<InStockDetail> buildSpecification(Integer orderId, Integer productId ) {
        return (root, query, cb) -> {
            return cb.and(
                    orderId != null ? cb.equal(root.join("order").get("orderId"), orderId) : null,
                    productId != null ? cb.equal(root.get("productId"), productId) : null
            );
        };
    }

    //验证关联实体，实体不存在抛出异常
    private void validateRelatedEntities(InStockDetail detail) {
        if (detail.getOrder() != null && detail.getOrder().getOrderId() != null) {
            Optional<InStockOrder> order = orderRepository.findById(detail.getOrder().getOrderId());
            if (order.isEmpty()) {
                throw new NoSuchElementException("InStockOrder not found with id: " + detail.getOrder().getOrderId());
            }
        }

        if (detail.getProductId() != null ) {
            Optional<Product> product = productRepository.findById(detail.getProductId());
            if (product.isEmpty()) {
                throw new NoSuchElementException("Product not found with id: " + detail.getProductId());
            }
        }
    }
}